#include <sys_config.h>
#include <osal/osal.h>
#include <basic_types.h>
#include <Mediatypes.h>

#include <api/libc/printf.h>
#include <api/libc/alloc.h>
#include <api/libc/string.h>

#include <hld/hld_dev.h>
#include <hld/vbi/vbi.h>
#include <hld/vbi/vbi_dev.h>
#include <hld/dis/vpo.h>
#include <api/libtsi/sec_tdt2.h>

#include "vbi_buffer.h"
#include "vbi_m3327.h"
#include <api/libttx/ttx_osd.h>
#define MAX_PAGE_FILTER_NUM 5 //cloud
extern struct vbi_m3327_private *g_vbi_priv;
extern struct vbi_config_par *g_vbi27_pconfig_par;
extern UINT8 *g_vbi27_ttx_by_osd;

static UINT8 g_default_g0_set =0xff;

static UINT8 page_start[8]={0,0,0,0,0,0,0,0};
static UINT8 g0_set[8];
static UINT8 second_g0_set[8];
static UINT8 g_transfer_mode = 1;
//UINT32 last_tmp_tick = 0xFFFFFFFF;
BOOL page_update_too_quick = FALSE;
static struct PBF_CB *pCurWrCB[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
static struct PBF_CB *pDecRdCB = NULL;
static UINT16 rd_page = 0xffff;
static struct PBF_CB *last_pCurWrCB[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};

static UINT8 last_mag;//last mag,0~7
static UINT8 transfer_mode;//transfer mode,(1:serial mode---0:parallel mode)
static UINT8 last_transfer_mode;

extern t_TTXDecCBFunc pCBPageUpdate;
extern UINT8 g_packet_exist[8][25];

//init it in vbi_m3327_init()
extern UINT8 * g_ttx_p26_nation;//(UINT8 *)((__MM_TTX_P26_NATION_BUF_ADDR & 0xfffffff) | 0x80000000);
//extern UINT8 *g_ttx_p26_data;//(UINT8 *)((__MM_TTX_P26_DATA_BUF_ADDR & 0xfffffff) | 0x80000000);

UINT8 last_temp_data[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};      // Used for fixing stream error of time show
UINT8 last_temp_data2[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};     // Backup data for next compare

extern OSAL_ID	ttx_subt_alarm_id;

#ifdef KAON_TTX_TIME
void set_kaon_ttx_time(UINT8 * temp)
{
	date_time dt;
	get_local_time(&dt);
    	temp[0] = dt.hour/10 + '0';
    	temp[1] = dt.hour % 10 + '0';
    	temp[2] = ':';
    	temp[3] = dt.min /10 + '0';
    	temp[4] = dt.min% 10 + '0';
    	temp[5] = ':';
    	temp[6] = dt.sec / 10 + '0';
    	temp[7] = dt.sec % 10 + '0';
}
#endif

static const UINT8 cor[8] =
{
    0x40, 0x10, 4, 8, 1, 0x20, 0x80, 2
};

static INLINE UINT8 hamming_8_4(UINT8 in)
{
	UINT32 A, B, C, D;

	if(TRUE == g_vbi27_pconfig_par->hamming_8_4_enable)
	{
    		D = in;
		D ^= D >> 4;
    		D ^= D >> 2;
    		D ^= D >> 1;

		if (!(D & 1))
    		{
        		A = in & 0xC5;
        		A ^= A >> 4;
        		A ^= A >> 2;
        		A ^= A >> 1;
        		B = in & 0x71;
        		B ^= B >> 4;
        		B ^= B >> 2;
        		B ^= B << 1;
        		C = in & 0x5C;
        		C ^= C >> 4;
        		C ^= C << 2;
        		C ^= C >> 1;
        		in ^= cor[(C & 4) | (B & 2) | (A & 1)];
	    	}
	}
	
    	return in;
}
static INLINE void hamming_24_18(UINT8 in1,UINT8 in2,UINT8 in3,UINT8* out1,UINT8* out2,UINT8* out3)
{
	if(TRUE == g_vbi27_pconfig_par->hamming_24_16_enable)
	{
		//reserved for feature usage
		;
	}
	*out1 = in1;
	*out2 = in2;
	*out3 = in3;
}

static INLINE UINT16 Hex2Dec2(UINT16 x)
{ //0x0000 - 0x0799    =>  100 - 899
    UINT16 y;
    UINT8 units=(x&0x000f);
    UINT8 tens=(x&0x00f0)>>4;
    UINT8 hunds=(x&0x0f00)>>8;
    //libc_printf("%s:%x%x%x\n",__FUNCTION__,hunds,tens,units);
    if(tens>9 /*||units>9*/)
    {
       // return 0xffff;
    }
    y = units + tens*10 + hunds*100;
    if(y<100)
        y += 800;
    //if(y>899)
    //{
       // y = 0xffff;
    //}
    return y;
}


static INLINE UINT16 Hex2Dec(UINT16 x)
{ //0x0000 - 0x0799    =>  100 - 899
	UINT16 y;
	UINT8 units=(x&0x000f);
	UINT8 tens=(x&0x00f0)>>4;
	UINT8 hunds=(x&0x0f00)>>8;
	if(tens>9 /*||units>9*/)
	{
		return 0xffff;
	}
	y = units + tens*10 + hunds*100;
	if(y<100)
		y += 800;
	if(y>899)
		y = 0xffff;
	return y;
}

static INLINE UINT8 Odd_dec(UINT8  data)
{
	UINT8 result=0;
	UINT8 cnt=0,i;
	for(i=0;i<8;i++)
	{
		if(data&(1<<i))
		{
			cnt++;
			result |= 1<<(7-i);
		}
	}

	if(!(cnt%2)) 
		return 0x20;
	
	//result = ((data&0x80)>>7) + ((data&0x40)>>5) + ((data&0x20)>>3) + ((data&0x10)>>1) \
	//	+ ((data&0x08)<<1) + ((data&0x04)<<3) + ((data&0x02)<<5) ;
	return result&0x7f;
}

static INLINE UINT16 x_mag(UINT8 addr1,UINT8 addr2)
{
	UINT16 result;
	result = ((addr1&0x40)>>6) + ((addr1&0x10)>>3) + (addr1&0x04);
	return result;
}

static INLINE UINT8 x_packet(UINT8 addr1,UINT8 addr2)
{
	UINT16 result;
	result = ((addr2&0x40)>>5) + ((addr2&0x10)>>2) + ((addr2&0x04)<<1) + ((addr2&0x01)<<4) + (addr1&0x01);
	return result;
}

static INLINE void x_page_cs(UINT8 *in, struct Header* head)
{
	UINT8 page_unit,page_tens,s1,s2,s3,s4;
	UINT8 i;
	UINT8 a[8];
	for(i=0;i<8;i++)
		a[i]=hamming_8_4(in[i]);

	page_unit = ((a[0]&0x40)>>6) + ((a[0]&0x10)>>3) + (a[0]&0x04) + ((a[0]&0x01)<<3);
	page_tens = ((a[1]&0x40)>>6) + ((a[1]&0x10)>>3) + (a[1]&0x04) + ((a[1]&0x01)<<3);
	s1 =  ((a[2]&0x40)>>6) + ((a[2]&0x10)>>3) + (a[2]&0x04) + ((a[2]&0x01)<<3);
	s2 =  ((a[3]&0x40)>>6) + ((a[3]&0x10)>>3) + (a[3]&0x04);
	s3 =  ((a[4]&0x40)>>6) + ((a[4]&0x10)>>3) + (a[4]&0x04) + ((a[4]&0x01)<<3);
	s4 =  ((a[5]&0x40)>>6) + ((a[5]&0x10)>>3) ;

//	PRINTF("page_tens == %x  page_unit == %x \n",page_tens,page_unit);

	head->page = (page_tens<<4) + page_unit;
//	PRINTF("page == %x  \n",head->page);
	head->s1= s1;
	head->s2= s2;
	head->s3= s3;
	head->s4= s4;
	head->control_bits=((a[3]&0x01)<<4)    \
					 +((a[5]&0x04)<<3)   \
					 +((a[5]&0x01)<<6)   \
					 +((a[6]&0x40)<<1)   \
					 +((a[6]&0x10)<<4)   \
					 +((a[6]&0x04)<<7)   \
					 +((a[6]&0x01)<<10) \
					 +((a[7]&0x40)<<5)   \
					 +((a[7]&0x10)<<10)  \
					 +((a[7]&0x04)<<11) \
					 +((a[7]&0x01)<<12) ;

}

static INLINE UINT8 x_packet_30(UINT8 *in, struct Header* head)
{
	UINT8 page_unit,page_tens,s1,s2,s3,s4,m1,m2,m3,mag;
	UINT8 i;
	UINT8 a[8];
	for(i=0;i<8;i++)
		a[i]=hamming_8_4(in[i]);

    //libc_printf("a[0]=0x%x,a[1]=0x%x\n",a[0],a[1]);
	page_unit = ((a[0]&0x40)>>6) + ((a[0]&0x10)>>3) + (a[0]&0x04) + ((a[0]&0x01)<<3);//same as page header
	page_tens = ((a[1]&0x40)>>6) + ((a[1]&0x10)>>3) + (a[1]&0x04) + ((a[1]&0x01)<<3);
 
    m1 = a[3]&0x01;
    m2 = a[5]&0x04;
    m3 = a[5]&0x01;
    mag = (m1)+(m2<<1)+(m3<<2);
	//libc_printf("page_tens == %x  page_unit == %x,\n",page_tens,page_unit);
	head->page = (page_tens<<4) + page_unit;
	
	return mag;

}

static INLINE UINT16 x_link(UINT8 *in ,UINT8 cur_mag)
{
	UINT8 mag, page_unit,page_tens,s1,s2,s3,s4;
	UINT16 page_id;
	UINT8 m1,m2,m3;
	UINT8 i;
	UINT8 a[6];
	for(i=0;i<6;i++)
		a[i]=hamming_8_4(in[i]);

	page_unit = ((a[0]&0x40)>>6) + ((a[0]&0x10)>>3) + (a[0]&0x04) + ((a[0]&0x01)<<3);
	page_tens = ((a[1]&0x40)>>6) + ((a[1]&0x10)>>3) + (a[1]&0x04) + ((a[1]&0x01)<<3);

	m1 = (a[3]&0x01);
	m2 = (a[5]&0x04)>>2;
	m3 = (a[5]&0x01);

	mag=(m3<<2) +(m2<<1) +(m1) ;//m3m2m1
	//mag= (mag+cur_mag)%8;
	/*if(mag>=cur_mag)
		mag -= cur_mag;
	else
		mag = cur_mag-mag;*/
	mag = mag^cur_mag;


	s1 =  ((a[2]&0x40)>>6) + ((a[2]&0x10)>>3) + (a[2]&0x04) + ((a[2]&0x01)<<3);
	s2 =  ((a[3]&0x40)>>6) + ((a[3]&0x10)>>3) + (a[3]&0x04);
	s3 =  ((a[4]&0x40)>>6) + ((a[4]&0x10)>>3) + (a[4]&0x04) + ((a[4]&0x01)<<3);
	s4 =  ((a[5]&0x40)>>6) + ((a[5]&0x10)>>3) ;

	page_id = Hex2Dec((mag<<8) + (page_tens<<4) + page_unit);  // 1-8
	//VBI_PRINTF("link page %d of page %d  =  %d \n",n, cb->page_id, page_id);
	return page_id;

}

static INLINE INT32  ttx_mem_cpy(UINT8 *dst,UINT8 *src,INT32  len)
{
	INT32 dwCount;
	INT32 ret = 0;
    if(MEMCMP(last_temp_data2,src,8)==0)            // Need not updata time
        return ret;
    else                                            // Update time
        MEMCPY(last_temp_data2,src,8);
	for(dwCount=0;dwCount<len;dwCount++)
	{
		if(*(dst+dwCount) != *(src+dwCount))
		{
			*(dst+dwCount) = *(src+dwCount);
			ret = -1;
		}
	}
	return ret;
}


#if 0
// this table generates the parity checks for hamm24/18 decoding.
// bit 0 is for test A, 1 for B, ...
// thanks to R. Gancarz for this fine table *g*

static char hamm24par[3][256] =
{
    { // parities of first byte
	 0, 33, 34,  3, 35,  2,  1, 32, 36,  5,  6, 39,  7, 38, 37,  4,
	37,  4,  7, 38,  6, 39, 36,  5,  1, 32, 35,  2, 34,  3,  0, 33,
	38,  7,  4, 37,  5, 36, 39,  6,  2, 35, 32,  1, 33,  0,  3, 34,
	 3, 34, 33,  0, 32,  1,  2, 35, 39,  6,  5, 36,  4, 37, 38,  7,
	39,  6,  5, 36,  4, 37, 38,  7,  3, 34, 33,  0, 32,  1,  2, 35,
	 2, 35, 32,  1, 33,  0,  3, 34, 38,  7,  4, 37,  5, 36, 39,  6,
	 1, 32, 35,  2, 34,  3,  0, 33, 37,  4,  7, 38,  6, 39, 36,  5,
	36,  5,  6, 39,  7, 38, 37,  4,  0, 33, 34,  3, 35,  2,  1, 32,
	40,  9, 10, 43, 11, 42, 41,  8, 12, 45, 46, 15, 47, 14, 13, 44,
	13, 44, 47, 14, 46, 15, 12, 45, 41,  8, 11, 42, 10, 43, 40,  9,
	14, 47, 44, 13, 45, 12, 15, 46, 42, 11,  8, 41,  9, 40, 43, 10,
	43, 10,  9, 40,  8, 41, 42, 11, 15, 46, 45, 12, 44, 13, 14, 47,
	15, 46, 45, 12, 44, 13, 14, 47, 43, 10,  9, 40,  8, 41, 42, 11,
	42, 11,  8, 41,  9, 40, 43, 10, 14, 47, 44, 13, 45, 12, 15, 46,
	41,  8, 11, 42, 10, 43, 40,  9, 13, 44, 47, 14, 46, 15, 12, 45,
	12, 45, 46, 15, 47, 14, 13, 44, 40,  9, 10, 43, 11, 42, 41,  8
    }, { // parities of second byte
	 0, 41, 42,  3, 43,  2,  1, 40, 44,  5,  6, 47,  7, 46, 45,  4,
	45,  4,  7, 46,  6, 47, 44,  5,  1, 40, 43,  2, 42,  3,  0, 41,
	46,  7,  4, 45,  5, 44, 47,  6,  2, 43, 40,  1, 41,  0,  3, 42,
	 3, 42, 41,  0, 40,  1,  2, 43, 47,  6,  5, 44,  4, 45, 46,  7,
	47,  6,  5, 44,  4, 45, 46,  7,  3, 42, 41,  0, 40,  1,  2, 43,
	 2, 43, 40,  1, 41,  0,  3, 42, 46,  7,  4, 45,  5, 44, 47,  6,
	 1, 40, 43,  2, 42,  3,  0, 41, 45,  4,  7, 46,  6, 47, 44,  5,
	44,  5,  6, 47,  7, 46, 45,  4,  0, 41, 42,  3, 43,  2,  1, 40,
	48, 25, 26, 51, 27, 50, 49, 24, 28, 53, 54, 31, 55, 30, 29, 52,
	29, 52, 55, 30, 54, 31, 28, 53, 49, 24, 27, 50, 26, 51, 48, 25,
	30, 55, 52, 29, 53, 28, 31, 54, 50, 27, 24, 49, 25, 48, 51, 26,
	51, 26, 25, 48, 24, 49, 50, 27, 31, 54, 53, 28, 52, 29, 30, 55,
	31, 54, 53, 28, 52, 29, 30, 55, 51, 26, 25, 48, 24, 49, 50, 27,
	50, 27, 24, 49, 25, 48, 51, 26, 30, 55, 52, 29, 53, 28, 31, 54,
	49, 24, 27, 50, 26, 51, 48, 25, 29, 52, 55, 30, 54, 31, 28, 53,
	28, 53, 54, 31, 55, 30, 29, 52, 48, 25, 26, 51, 27, 50, 49, 24
    }, { // parities of third byte
	63, 14, 13, 60, 12, 61, 62, 15, 11, 58, 57,  8, 56,  9, 10, 59,
	10, 59, 56,  9, 57,  8, 11, 58, 62, 15, 12, 61, 13, 60, 63, 14,
	 9, 56, 59, 10, 58, 11,  8, 57, 61, 12, 15, 62, 14, 63, 60, 13,
	60, 13, 14, 63, 15, 62, 61, 12,  8, 57, 58, 11, 59, 10,  9, 56,
	 8, 57, 58, 11, 59, 10,  9, 56, 60, 13, 14, 63, 15, 62, 61, 12,
	61, 12, 15, 62, 14, 63, 60, 13,  9, 56, 59, 10, 58, 11,  8, 57,
	62, 15, 12, 61, 13, 60, 63, 14, 10, 59, 56,  9, 57,  8, 11, 58,
	11, 58, 57,  8, 56,  9, 10, 59, 63, 14, 13, 60, 12, 61, 62, 15,
	31, 46, 45, 28, 44, 29, 30, 47, 43, 26, 25, 40, 24, 41, 42, 27,
	42, 27, 24, 41, 25, 40, 43, 26, 30, 47, 44, 29, 45, 28, 31, 46,
	41, 24, 27, 42, 26, 43, 40, 25, 29, 44, 47, 30, 46, 31, 28, 45,
	28, 45, 46, 31, 47, 30, 29, 44, 40, 25, 26, 43, 27, 42, 41, 24,
	40, 25, 26, 43, 27, 42, 41, 24, 28, 45, 46, 31, 47, 30, 29, 44,
	29, 44, 47, 30, 46, 31, 28, 45, 41, 24, 27, 42, 26, 43, 40, 25,
	30, 47, 44, 29, 45, 28, 31, 46, 42, 27, 24, 41, 25, 40, 43, 26,
	43, 26, 25, 40, 24, 41, 42, 27, 31, 46, 45, 28, 44, 29, 30, 47
    }
};

// table to extract the lower 4 bit from hamm24/18 encoded bytes

static char hamm24val[256] =
{
      0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,  0,  1,  1,  1,  1,
      2,  2,  2,  2,  3,  3,  3,  3,  2,  2,  2,  2,  3,  3,  3,  3,
      4,  4,  4,  4,  5,  5,  5,  5,  4,  4,  4,  4,  5,  5,  5,  5,
      6,  6,  6,  6,  7,  7,  7,  7,  6,  6,  6,  6,  7,  7,  7,  7,
      8,  8,  8,  8,  9,  9,  9,  9,  8,  8,  8,  8,  9,  9,  9,  9,
     10, 10, 10, 10, 11, 11, 11, 11, 10, 10, 10, 10, 11, 11, 11, 11,
     12, 12, 12, 12, 13, 13, 13, 13, 12, 12, 12, 12, 13, 13, 13, 13,
     14, 14, 14, 14, 15, 15, 15, 15, 14, 14, 14, 14, 15, 15, 15, 15,
      0,  0,  0,  0,  1,  1,  1,  1,  0,  0,  0,  0,  1,  1,  1,  1,
      2,  2,  2,  2,  3,  3,  3,  3,  2,  2,  2,  2,  3,  3,  3,  3,
      4,  4,  4,  4,  5,  5,  5,  5,  4,  4,  4,  4,  5,  5,  5,  5,
      6,  6,  6,  6,  7,  7,  7,  7,  6,  6,  6,  6,  7,  7,  7,  7,
      8,  8,  8,  8,  9,  9,  9,  9,  8,  8,  8,  8,  9,  9,  9,  9,
     10, 10, 10, 10, 11, 11, 11, 11, 10, 10, 10, 10, 11, 11, 11, 11,
     12, 12, 12, 12, 13, 13, 13, 13, 12, 12, 12, 12, 13, 13, 13, 13,
     14, 14, 14, 14, 15, 15, 15, 15, 14, 14, 14, 14, 15, 15, 15, 15
};



// mapping from parity checks made by table hamm24par to error
// results return by hamm24.
// (0 = no error, 0x0100 = single bit error, 0x1000 = double error)

static short hamm24err[64] =
{
    0x0000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
    0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
    0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
    0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
    0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100,
    0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000,
};

// mapping from parity checks made by table hamm24par to faulty bit
// in the decoded 18 bit word.

static int hamm24cor[64] =
{
    0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000,
    0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000,
    0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000,
    0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000,
    0x00000, 0x00000, 0x00000, 0x00001, 0x00000, 0x00002, 0x00004, 0x00008,
    0x00000, 0x00010, 0x00020, 0x00040, 0x00080, 0x00100, 0x00200, 0x00400,
    0x00000, 0x00800, 0x01000, 0x02000, 0x04000, 0x08000, 0x10000, 0x20000,
    0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000, 0x00000,
};

int
hamm24(UINT8 *p, int *err)
{
    int e;
    int x;
    UINT8 tmp, tmp1, i, j;

    for(j = 0; j < 3; j++)
    {
        tmp1 = *(p+j);
        tmp = 0;
        for(i = 0; i < 8; i++)
            tmp |= (((tmp1 >> (7-i))&1)<<i);
        *(p+j) = tmp;
    }

    e = hamm24par[0][p[0]] ^ hamm24par[1][p[1]] ^ hamm24par[2][p[2]];
    x = hamm24val[p[0]] + p[1] % 128 * 16 + p[2] % 128 * 2048;

    *err += hamm24err[e];
    return x ^ hamm24cor[e];
}
#endif

static UINT8 last_row,last_col;//to store row and col for more than 13 x/26 packet
static UINT16 last_p26_page_id=0, last_p26_sub_page_id=0;
static BOOL bPacket26=FALSE;

static UINT8 last_packet[8]={0,0,0,0,0,0,0,0};
static UINT16 last_page_id[8]={0,0,0,0,0,0,0,0};

static UINT16 last_sub_page_id[8]={0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff};
static UINT8 bSaveSubpage=FALSE;

static UINT8 last_page_number[8] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};//page uints+page tens
static BOOL bShowPage=FALSE;
static BOOL erase_page=FALSE;
static BOOL bChangeMag = FALSE;//for some special stream have a page serial mode and a page parallel mode  
//static BOOL bCheck_p26 = FALSE;//for stream: x/n,x/26,x/n+1.....
static UINT16 g_inital_page = 0xFF;
static UINT16 last_erase_bit[2] = {0,0};
static UINT8 inital_page_status = 2;//TTXENG_TEXT;
static UINT16 page_transfered_num = 0;//cloud, to judge when to filter blank header
static UINT16 first_ttx_page = 0xff;//cloud, first non-ttxsubtitle page id

UINT16 get_first_ttx_page()
{
    return first_ttx_page;
}

UINT16 get_inital_page()//cloud
{
    return g_inital_page;
}

UINT8 get_inital_page_status()
{
    return inital_page_status;
}

BOOL get_bSaveSubpage()
{
    return bSaveSubpage;
}

UINT32 get_packet26_nation_map(UINT16 page, UINT16 line, UINT16 i)
{//use this function to replace GET_P26_NATION_MAP to avoid bug, cloud
    UINT32 pos;
    UINT32 ret;
    if(page<100 || page>899)
        return 0;
    pos = ((page-100)*(25*20)+line*20+(i>>1));

    ret = ((g_ttx_p26_nation[pos]>>((i&1)*4))&0xf);
    return ret;
}

static UINT32 page_rec_data[8] = {1,1,1,1,1,1,1,1};
//#define PRINTF_PAGE_PACKET
#ifdef PRINTF_PAGE_PACKET
static UINT16 g_debug_page_id = 0xffff; //printf special page packet
static UINT8 g_debug_line = 0xFF; //debug special packet
static UINT8 g_debug_p26 = 0;	//debug 26 packet of special page
static UINT8 g_disable_p26 = 0;//disable p26
#endif
extern UINT16 cur_page;
extern UINT16 WaitPage;

//UINT8 ttx_page_count = 0;
//BOOL page_erase = FALSE;           // added for clean ttx_subt line that is not needed 


void parse_ttx_data(UINT8 *data) //
{
	UINT8 i,j,temp_mag=0;
	UINT8  addr1,addr2,packet,designation;
	UINT8 mag,abs_mag;
	UINT16 page_id=0 ,link_page_id;
	UINT8 ham1,ham2,ham3;
	UINT16 sub_page_id=0xffff; //cloud
	struct Header head;
	UINT8 *ptr;
	UINT8 temp_data[40];
	UINT8 last_data[42];//for repeated same packet of same mag.
	UINT8 p26_address, p26_mode,  p26_data, p26_nation, row = 0, col=0;
	UINT8 page_number = 0xff;//current page uints+page tens
	UINT8 SuppressHeader,ErasePage,InterruptedSequence,Subtitle;
	struct PBF_CB *check_cb = NULL;
	if(MEMCMP(data,last_data,42)==0)
		return ;
	else
	{
		MEMCPY(last_data,data,42);
	}
	addr1 = hamming_8_4(*data++); //
	addr2 = hamming_8_4(*data++); //
	mag = x_mag(addr1,addr2); // make sure 0 -- 7
	packet = x_packet(addr1,addr2);	
	//if(mag==3)
	 //   libc_printf("mag=%d, packet=%d\n",mag,packet);
#if 0
	//some stream transfer packet like:1,2,3,4....23,24,26
	if(packet==0 && last_mag!=0xf && (last_packet[last_mag]==26 || bCheck_p26 == TRUE)&& last_pCurWrCB[last_mag]!=NULL &&g_ttx_p26_data!=NULL && g_ttx_p26_nation!=NULL && TRUE == g_vbi27_pconfig_par->parse_packet26_enable)
	{
	
	//libc_printf("last_pCurWrCB[last_mag]->page_id=%d\n",last_pCurWrCB[last_mag]->page_id);
	
	for(j=1;j<=23;j++)
	
	{
		
	ptr = last_pCurWrCB[last_mag]->buf_start + j*40;
		
	for(i=0;i<40;i++)
		
	{
			
	if(((g_ttx_p26_data[j*40+i])>>7 == 1)||(((g_ttx_p26_data[j*40+i])>>7 == 0)))//&&GET_P26_NATION_MAP(last_pCurWrCB[last_mag]->page_id, j, i) == 0xf))
			
	{
				
	if(get_packet26_nation_map(last_pCurWrCB[last_mag]->page_id, j, i)==0xf)
				
	//if(GET_P26_NATION_MAP(last_pCurWrCB[last_mag]->page_id, j, i) == 0xf)
				
	*(ptr+i)= g_ttx_p26_data[j*40+i];
			
	}
		
	}
	
	}
	
	bCheck_p26 = FALSE;
	}
#endif
	///////////////////////////////////////////////////////////////////////////////////////////////////////	
#ifdef PRINTF_PAGE_PACKET
	if(packet !=0 && mag<8 && last_pCurWrCB[mag]!=NULL && last_pCurWrCB[mag]->page_id==g_debug_page_id)
	{
		libc_printf("P%d, ", packet);
		if(g_debug_line == packet)
		{
			soc_printf(" ");//for debug line of special page
		}
	}
#endif
	if(packet == 0x00)
	{
		if(mag>7)
			return;
		x_page_cs(data,&head);
		if(head.page != 0xff)  //
		{
			page_rec_data[mag] = 1;
            page_number = Hex2Dec2(head.page)-800;
            page_id = Hex2Dec2( (mag<<8) + head.page); //100 ~899,0~99->800~899
			if(page_id == 0xffff)
			{
				page_rec_data[mag] = 0;
				return;
			}
			InterruptedSequence= ((head.control_bits & 0x0200)==0x0200)?0x01:0x00;
			Subtitle= ((head.control_bits & 0x0040)==0x0040)?0x01:0x00;			
			transfer_mode = ((head.control_bits & 0x0800)==0x0800)?0x01:0x00;//1:serial mode---0:parallel mode
			g_transfer_mode = transfer_mode;

		    #ifdef PRINTF_PAGE_PACKET  
	
	      	if(page_id == g_debug_page_id)   
	
		{
	
				libc_printf("\nPg %d S[%d]:", page_id, transfer_mode);
	
         	}
            	    #endif
			if(TRUE == g_vbi27_pconfig_par->ttx_sub_page)
			{
				sub_page_id = Hex2Dec(((head.s2)<<4) + head.s1)-800;//cloud,0~79
				if(sub_page_id>79)
					return;
			}

			//ttx_page_count++;
			//if(ttx_page_count>100)
			//{
			//	ttx_page_count=0;
			//	osal_task_sleep(20);
			//}
			if(transfer_mode == 1)
			{
				if(page_number!=last_page_number[mag] || mag!=last_mag ||Subtitle==1)
				{
					if(last_mag!=0xf && page_start[last_mag]==1)
					{
						page_start[last_mag]=0;
						bShowPage=TRUE;
					}
				}
				page_start[mag]=1;//begin to parse a new page
			}
			else
			{
				if(last_mag==0xf)
					page_start[mag]=1;
				else if(mag!=last_mag && last_transfer_mode ==1)
				{
					for(i=0,j=0;i<25;i++)
					{
						if(g_packet_exist[last_mag][i]==1)
							j++;
					}
					if(j>=2) //if last mag page have 1 line data, the page should be showed. guoping fix fulan bug 2008-10-30,stream file 12633H22000 K-TV TTX 29E can not display *.ts
					{
						bShowPage=TRUE;
						bChangeMag =TRUE;
					}
				}
				else if(/*page_number!=last_page_number[mag] && */page_start[mag]==1 && last_page_number[mag]!=0xff)
				{
					page_start[mag]=1;//old page end,begin to receive new page
					if((last_page_number[mag]==0 || last_page_number[mag]==0xff) && last_packet[mag]==0)
						bShowPage=FALSE;
					else
						bShowPage=TRUE;
				}
				else if(page_number==last_page_number[mag] && page_start[mag]==1 && Subtitle==1)
				{
					bShowPage=TRUE;
				}
				page_start[mag]=1;
			}
			if(bShowPage == TRUE)
			{//display last page
			    BOOL ttx_subt_update = FALSE;
				if(transfer_mode == 1)
					temp_mag=last_mag;
				else
					temp_mag=mag;
				if(bChangeMag==TRUE && transfer_mode==0)
				{
					temp_mag=last_mag;
					bChangeMag = FALSE;
				}
				if(last_pCurWrCB[temp_mag]->valid==0)
					page_transfered_num++;//cloud
				last_pCurWrCB[temp_mag]->valid = 1; // move here from pbf_wr_req(), to make sure cb of the page finish.
				last_pCurWrCB[temp_mag]->complement_line = 0;
				if(pCBPageUpdate!=NULL)
				{
					//if(mag==3 )//&& last_pCurWrCB[temp_mag]->page_id==600 )//&& pCurWrCB[mag]->sub_page_id==7)
					//    LIBC_PRINTF("display page1,page_id=%d,temp_mag=%d,subpage_id=%d,bShowPage=%d\n",last_pCurWrCB[temp_mag]->page_id,temp_mag,last_pCurWrCB[temp_mag]->sub_page_id,bShowPage);
					if(TRUE == g_vbi27_pconfig_par->ttx_sub_page)
						bSaveSubpage=TRUE;
					j=0;
					for(i=1;i<24;i++)
					{
						if( g_packet_exist[temp_mag][i] !=1 )
						{
							if(TRUE == g_vbi27_pconfig_par->parse_packet26_enable && g_packet_exist[temp_mag][i]==26)
							{
								g_packet_exist[temp_mag][i]=1;
								j++;
							}
							else	 if(g_packet_exist[temp_mag][i]==0)
							{
							 if(1==last_pCurWrCB[temp_mag]->ErasePage)
								MEMSET(last_pCurWrCB[temp_mag]->buf_start+i*40, 0x20, 40);//cloud
								//pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
							}
						}
						else
							j++;
						//if(g_packet_exist[temp_mag][i]==1) 
						//{
							//pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
						//}
					}
					if(j>0)
					{      
                       				 if(last_pCurWrCB[temp_mag]->page_id == cur_page && WaitPage == 0xffff)// only check current showing page
                       				 {
                           				 UINT32 tmp_tick = osal_get_tick();
                            				struct PBF_CB *tmp_cb = NULL;
                          					  UINT32 last_tmp_tick;
                            
                           				 if(pbf_wr_req(last_pCurWrCB[temp_mag]->page_id, &tmp_cb) == RET_SUCCESS && tmp_cb != NULL)
                           				 {
                                 					  last_tmp_tick = tmp_cb->page_update_tick;
                                
                                 					 if(last_pCurWrCB[temp_mag]->Subtitle != 1)
			      					 { // Now we only check normal ttx 
                                   						 if((tmp_tick - last_tmp_tick) < 500)
                                    					{
                                        						page_update_too_quick = TRUE;
                                   		 				}
                                   						 else
                                   		 				{
                                       		 				page_update_too_quick = FALSE;
                                    					 }
                                   		 				if(0)//(page_update_too_quick == TRUE)
                                   		 				{
                                       		 // if page update too quick we do nothing.
                                   		 				}
                                   						 else
                                   		 				{
                									for(i=1;i<24;i++)
                									{
                										pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
                									}
                                    					 }
                                    					tmp_cb->page_update_tick = tmp_tick;
                              					  }
                                					 else
			    					 {
                                      					 for(i=1;i<24;i++)
                                           						pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
                               					 }
                         					 }
                         					else
                        					 {
                              					  for(i=1;i<24;i++)
                                   					 pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
                         					 }
                    				 }
                   				 else
                   				 {
                           				 for(i=1;i<24;i++)
                              					  pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
                    				 }
                        
					}

					if(last_pCurWrCB[temp_mag]->pack24_exist==1)
						pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,24);
					for(i=1;i<24;i++)
					{
						if(g_packet_exist[temp_mag][i]==1)
						{
							erase_page=TRUE;
							break;
						}
					}
					if(i==24)
						erase_page=FALSE;
					if(TRUE == g_vbi27_pconfig_par->erase_unknown_packet && erase_page==TRUE && last_pCurWrCB[temp_mag]->Subtitle!=1)
					{
						if((last_pCurWrCB[temp_mag]->MagazineSerial==1) 
						&& (last_pCurWrCB[temp_mag]->ErasePage==1) && (last_erase_bit[0]==1) &&(last_pCurWrCB[temp_mag]->page_id == last_erase_bit[1]))
						{
						}
						else
						{
							for(i=1;i<24;i++)
							{
								if(g_packet_exist[temp_mag][i]==0)
								{
									//if(last_pCurWrCB[temp_mag]->page_id==102)
									//   libc_printf("g_packet_exist[temp_mag][%d]=%d\n",i,g_packet_exist[temp_mag][i]);
									if((last_pCurWrCB[temp_mag]->MagazineSerial==0 && last_pCurWrCB[temp_mag]->page_id!=600) || last_pCurWrCB[temp_mag]->MagazineSerial==1)
									{
										MEMSET(last_pCurWrCB[temp_mag]->buf_start+i*40, 0x20, 40);//cloud
										pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
									}
								}
							}
						}
					}
					if(TRUE == g_vbi27_pconfig_par->ttx_sub_page)
					{
						bSaveSubpage=FALSE;
					}
				} 
				bShowPage=FALSE;
				if(last_pCurWrCB[temp_mag]->Subtitle!=1)
				{
					last_erase_bit[0]= last_pCurWrCB[temp_mag]->ErasePage;
					last_erase_bit[1]= last_pCurWrCB[temp_mag]->page_id;
				}
			}
			if(pbf_wr_req(page_id , &pCurWrCB[mag]) == RET_FAILURE) //mag0 <-> page 800-899
			{
				//libc_printf("pbf_wr_req failure \n");
				return ;//ASSERT(0);
			}
			if(TRUE == g_vbi27_pconfig_par->parse_packet26_enable)
				MEMSET(g_ttx_p26_nation+(page_id-100)*(25*40>>1), 0x00, (25*40>>1));//cloud
			pCurWrCB[mag]->sub_page_id = sub_page_id;//cloud
			pCurWrCB[mag]->page_id = page_id;
			pCurWrCB[mag]->ErasePage= ((head.control_bits & 0x0010)==0x0010)?0x01:0x00;
			pCurWrCB[mag]->UpdateIndicator= ((head.control_bits & 0x0100)==0x0100)?0x01:0x00;
			pCurWrCB[mag]->NationOption= (head.control_bits)>>12 ;
			pCurWrCB[mag]->SuppressHeader = ((head.control_bits & 0x0080)==0x0080)?0x01:0x00;
			pCurWrCB[mag]->InhibitDisplay     = ((head.control_bits & 0x0400)==0x0400)?0x01:0x00;
			pCurWrCB[mag]->MagazineSerial = ((head.control_bits & 0x0800)==0x0800)?0x01:0x00;
			pCurWrCB[mag]->Newsflash= ((head.control_bits & 0x0020)==0x0020)?0x01:0x00;
			pCurWrCB[mag]->Subtitle= ((head.control_bits & 0x0040)==0x0040)?0x01:0x00;
			pCurWrCB[mag]->InterruptedSequence= ((head.control_bits & 0x0200)==0x0200)?0x01:0x00;
			pCurWrCB[mag]->G0_set = g0_set[mag];
			pCurWrCB[mag]->Second_G0_set = second_g0_set[mag];
	/*		if(pCurWrCB[mag]->Second_G0_set==0)//if no 28packet and 29packet, national optional of Second G0 same as G0
			{
				pCurWrCB[mag]->Second_G0_set = (pCurWrCB[mag]->NationOption & 0x7);
			}
*/
			if((g_inital_page!=0xff) && (pCurWrCB[mag]->page_id == g_inital_page))//acoid show blank screen before show ttx subtitle
			{
				if(pCurWrCB[mag]->Subtitle==1)
					inital_page_status = 1;//TTXENG_SUBT;
				else
					inital_page_status = 2;//TTXENG_TEXT;
			}
			if(pCurWrCB[mag]->Subtitle!=1)
				first_ttx_page = pCurWrCB[mag]->page_id;
			//   libc_printf("page_id=%d,sub_page_id=%d,ErasePage=%d,UpdateIndicator=%d,SuppressHeader=%d,InhibitDisplay=%d,MagazineSerial=%d,Newsflash=%d,Subtitle=%d,InterruptedSequence=%d\n",
			//   page_id,sub_page_id,pCurWrCB[mag]->ErasePage,pCurWrCB[mag]->UpdateIndicator,pCurWrCB[mag]->SuppressHeader,pCurWrCB[mag]->InhibitDisplay,pCurWrCB[mag]->MagazineSerial,pCurWrCB[mag]->Newsflash,
			//   pCurWrCB[mag]->Subtitle,pCurWrCB[mag]->InterruptedSequence);
			//		if(TRUE == g_vbi27_pconfig_par->parse_packet26_enable)
			//		{
			//		if(pCurWrCB[mag]->page_id!=last_page_id[mag]||
			//             ((TRUE == g_vbi27_pconfig_par->ttx_sub_page) && pCurWrCB[mag]->sub_page_id!=last_sub_page_id[mag])||
			//             (mag!=last_mag && transfer_mode==1 && last_transfer_mode ==0))
			//		{
			// 			MEMSET(g_ttx_p26_data, 0x00, 25*40);//cloud
			//		}
			//		}
			// time filling start
			if(rd_page  != 0xffff && pCurWrCB[mag]->SuppressHeader == 0 && pCurWrCB[mag]->InterruptedSequence == 0 )//&& pCurWrCB[mag]->ErasePage!=1)
			{
				if(transfer_mode==1 || (transfer_mode==0 && mag==1))
				{
					ptr = pDecRdCB->buf_start+32;
#ifndef KAON_TTX_TIME
					for(i=0;i<8;i++)
					{
						temp_data[i] = Odd_dec(*(data +32+i));
					}
		
                    if(temp_data[2]!=':' && temp_data[5]==':')      // ':'error position adjust
		
                    {
		
                        UINT8 tmp;
		
                        tmp = temp_data[2];
		
                        temp_data[2] = temp_data[5];
		
                        temp_data[5] = tmp; 
		
                    } 
	
//                    if(temp_data[2]!=':' || temp_data[5]!=':')      // ':'error position adjust
	
//                    {
	
//                        temp_data[2] = temp_data[5] = ':';
	
//                    } 
#else
					set_kaon_ttx_time(temp_data);
#endif
	
				if(ttx_mem_cpy(ptr,temp_data,8) != 0)
	
				{ 
		
                        if(temp_data[7]==0x20 && last_temp_data[7]!=0xff)// Last byte of temp_data is space and 
		
                        {                                                // last_temp_data[7] contain valid data
			#if 0
                            if(last_temp_data[7] == 0x39)                // Calculate data will be shown
                                temp_data[7] = 0x30;
                            else
                                temp_data[7] = last_temp_data[7] + 1;
                            ptr[7] = temp_data[7];
			#else  //mask flicker
				temp_data[7]=last_temp_data[7];
                            	ptr[7] = temp_data[7];
			#endif
		
                     }
                        		MEMCPY(last_temp_data,temp_data,8);             // Backup cur temp_data for next use
                        		
                        		if(pCBPageUpdate!=NULL)
                        			{
                        				if(pDecRdCB->Subtitle)
                        				{
                        				}
						else
						pCBPageUpdate(pDecRdCB->page_id,0x00);
                        			}
				//		if(pCBPageUpdate!=NULL)
				//	pCBPageUpdate(pDecRdCB->page_id,0x00);
					}
				}
			}
			// time filling end
			if(pCurWrCB[mag]->ErasePage == 0x01&&(0!=pCurWrCB[mag]->sub_page_id||1==pCurWrCB[mag]->Subtitle))
			{
				MEMSET(pCurWrCB[mag]->buf_start, 0x20, 1000);
				pCurWrCB[mag]->pack24_exist = 0;
				pCurWrCB[mag]->complement_line = 0;
			}
			ptr = pCurWrCB[mag]->buf_start;
			*ptr++ = 0x20;
			*ptr++ = (UINT8)(page_id/100) + 0x30;
			*ptr++ = (UINT8)((page_id%100)/10) + 0x30;
			*ptr++ = (UINT8)((page_id%100)%10) + 0x30;
			*ptr++ = 0x20;
			*ptr++ = 0x20;
			*ptr++ = 0x20;
			*ptr++ = 0x20;
			for(i=0;i<32;i++)
			{
				*ptr++ = Odd_dec(*(data+8+i));
			}
			if((TRUE == g_vbi27_pconfig_par->user_fast_text) && (pCurWrCB[mag]->pack24_exist ==0))
			{
				if((pCurWrCB[mag]->ErasePage == 0x01)&&
				((g_vbi27_pconfig_par->erase_unknown_packet == FALSE)||(pCurWrCB[mag]->Subtitle==1)))
				{//avoid refresh too quickly
					for(i=0;i<24;i++)
					{
						if(pCBPageUpdate!=NULL)
							pCBPageUpdate(pCurWrCB[mag]->page_id,i);
					}
				}
				else
				{
					if(pCBPageUpdate!=NULL)
						pCBPageUpdate(pCurWrCB[mag]->page_id,0);	
				}
			}
			else
			{
				//in case page that need Erase, for avoid flash, show not erase osd directly
				//only need reset page memory
				if((pCurWrCB[mag]->ErasePage == 0x01)&&
				(/*(g_vbi27_pconfig_par->erase_unknown_packet == FALSE)||*/(pCurWrCB[mag]->Subtitle==1)))
				{
					for(i=0;i<25;i++)
					{
						if(pCBPageUpdate!=NULL)
							pCBPageUpdate(pCurWrCB[mag]->page_id,i);
					}
				}
				else
				{          
					if(pCBPageUpdate!=NULL)
						pCBPageUpdate(pCurWrCB[mag]->page_id,0); 
				}
			}
			if((pCurWrCB[mag]->ErasePage == 0x01) || (pCurWrCB[mag]->Subtitle== 0x01) || (last_page_id[mag] != pCurWrCB[mag]->page_id) )
			{
				for(i=0;i<25;i++)
					g_packet_exist[mag][i]=0;
			}
			pCurWrCB[mag]->pack24_exist = 0;
			last_page_number[mag] = page_number;//cloud
			last_pCurWrCB[mag] = pCurWrCB[mag];//cloud
			last_mag = mag;//cloud
			last_page_id[mag]= pCurWrCB[mag]->page_id;
			last_sub_page_id[mag]=pCurWrCB[mag]->sub_page_id;
			last_transfer_mode =transfer_mode;
			//for(i=0;i<25;i++)
			//	g_packet_exist[mag][i]=0;
		}
		else if(head.page == 0xff)
		{
			page_rec_data[mag] = 0;
			#ifdef PRINTF_PAGE_PACKET
			if(page_id == g_debug_page_id)
			{
				libc_printf("Pg %d End\n", page_id);
			}
			#endif
			//if( head.s4 == 0x3 && head.s3 == 0xF && head.s2 == 0x7 && head.s1 == 0xF)
			//	return;// no FF-3F7F transmit
			//if(mag==4)
			//    libc_printf("head.page == 0xff,,,,last_page_number[mag]=%d,page_start[last_mag]=%d,page_start[mag]=%d,transfer_mode=%d\n",last_page_number[mag],page_start[last_mag],page_start[mag],transfer_mode);
			transfer_mode = ((head.control_bits & 0x0800)==0x0800)?0x01:0x00;//cloud
			if(transfer_mode!=g_transfer_mode)
				return;
			if(page_start[mag]== 1 && transfer_mode == 0)
			{
				bShowPage=TRUE;
			}
			else if(page_start[last_mag]== 1 && transfer_mode == 1)
				bShowPage=TRUE;
			else
				bShowPage=FALSE;
			if(bShowPage == TRUE)
			{ //display last page
			    BOOL ttx_subt_update = FALSE;
				if(transfer_mode == 1)
					temp_mag=last_mag;
				else
					temp_mag=mag;
				if(last_pCurWrCB[temp_mag]->valid==0)
					page_transfered_num++;//cloud
				last_pCurWrCB[temp_mag]->valid = 1; // move here from pbf_wr_req(), to make sure cb of the page finish.
				last_pCurWrCB[temp_mag]->complement_line = 0;
               		if(pCBPageUpdate!=NULL)
				{
					//if(mag ==3 )//&& last_pCurWrCB[temp_mag]->page_id==600)
					//    LIBC_PRINTF("display page2,page_id=%d,temp_mag=%d,last_pCurWrCB[temp_mag]->sub_page_id=%d,bShowPage=%d\n",last_pCurWrCB[temp_mag]->page_id,temp_mag,last_pCurWrCB[temp_mag]->sub_page_id,bShowPage);
					if(TRUE == g_vbi27_pconfig_par->ttx_sub_page)
						bSaveSubpage=TRUE;
					j=0;
					for(i=1;i<24;i++)
					{
						if( g_packet_exist[temp_mag][i] !=1 )
						{
							if(TRUE == g_vbi27_pconfig_par->parse_packet26_enable && g_packet_exist[temp_mag][i]==26)
							{
								g_packet_exist[temp_mag][i]=1;
								j++;
							}
							else	 if(g_packet_exist[temp_mag][i]==0)
							{
                             if(1==last_pCurWrCB[temp_mag]->ErasePage)
								MEMSET(last_pCurWrCB[temp_mag]->buf_start+i*40, 0x20, 40);//cloud
								//pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
							}
						}
						else
							j++;
//						if(g_packet_exist[temp_mag][i]==1) 
//						{
							//pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
//						}
					}
					if(j>0&&(0!=last_pCurWrCB[temp_mag]->sub_page_id||1==last_pCurWrCB[temp_mag]->Subtitle||(last_pCurWrCB[temp_mag]->page_id == cur_page && WaitPage == 0xffff)))
					{     
					
                       			for(i=1;i<24;i++)
                                		pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
					}
					if(last_pCurWrCB[temp_mag]->pack24_exist==1)
						pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,24);
					for(i=1;i<24;i++)
					{
						if(g_packet_exist[temp_mag][i]==1)
						{
							erase_page=TRUE;
							break;
						}
					}
					if(i==24)
						erase_page=FALSE;
					if(TRUE == g_vbi27_pconfig_par->erase_unknown_packet && erase_page==TRUE && last_pCurWrCB[temp_mag]->Subtitle!=1)
					{
						if((last_pCurWrCB[temp_mag]->MagazineSerial==1) && (last_pCurWrCB[temp_mag]->ErasePage==1) && (last_erase_bit[0]==1) &&(last_pCurWrCB[temp_mag]->page_id == last_erase_bit[1]))
						{
						}
						else
						{
							for(i=1;i<24;i++)
							{
								if(g_packet_exist[temp_mag][i]==0)
								{
									//if((last_pCurWrCB[temp_mag]->MagazineSerial==0 && i<=21 && i>1) || last_pCurWrCB[temp_mag]->MagazineSerial==1)
									if(0!= last_pCurWrCB[temp_mag]->sub_page_id|| 1==last_pCurWrCB[temp_mag]->Subtitle)
									{
										MEMSET(last_pCurWrCB[temp_mag]->buf_start+i*40, 0x20, 40);//cloud
										pCBPageUpdate(last_pCurWrCB[temp_mag]->page_id,i);
									}
								}
							}
						}
					}
					if(TRUE == g_vbi27_pconfig_par->ttx_sub_page)
					{
						bSaveSubpage=FALSE;
						last_sub_page_id[temp_mag]=last_pCurWrCB[temp_mag]->sub_page_id;
					}
					last_page_id[temp_mag]=last_pCurWrCB[temp_mag]->page_id;
				}
				page_start[temp_mag]= 0; //as terminator,last page finished
				bShowPage=FALSE;
				if(last_pCurWrCB[temp_mag]->Subtitle!=1)
				{
					last_erase_bit[0]= last_pCurWrCB[temp_mag]->ErasePage;
					last_erase_bit[1]= last_pCurWrCB[temp_mag]->page_id;
				}
			}
			last_page_number[mag] = 0xff;//cloud
			last_mag = mag;//cloud
			if(rd_page  == 0xffff)
				return ;
			// time filling start//
			SuppressHeader = ((head.control_bits & 0x0080)==0x0080)?0x01:0x00;
			ErasePage = ((head.control_bits & 0x0010)==0x0010)?0x01:0x00;//cloud
			if(pDecRdCB->SuppressHeader == 0 && SuppressHeader == 0 )//&& ErasePage == 0)
			{
				if(transfer_mode==1 || (transfer_mode==0 && mag==1))
				{
					ptr = pDecRdCB->buf_start+32;
#ifndef KAON_TTX_TIME
					for(i=0;i<8;i++)
					{
						temp_data[i] = Odd_dec(*(data +32+i));
					}
	
                    if(temp_data[2]!=':' && temp_data[5]==':')      // ':'error position adjust
	
                    {
	
                        UINT8 tmp;
	
                        tmp = temp_data[2];
	
                        temp_data[2] = temp_data[5];
	
                        temp_data[5] = tmp; 
	
                    } 
	
//                    if(temp_data[2]!=':' || temp_data[5]!=':')      // ':'error position adjust
	
//                    {
	
//                        temp_data[2] = temp_data[5] = ':';
	
//                    } 
#else
					set_kaon_ttx_time(temp_data);
#endif
					if(ttx_mem_cpy(ptr,temp_data,8) != 0)
					{
                        if(temp_data[7]==0x20 && last_temp_data[7]!=0xff)// Last byte of temp_data is space and 
                        {                                                // last_temp_data[7] contain valid data
                            if(last_temp_data[7] == 0x39)                // Calculate data will be shown
                                temp_data[7] = 0x30;
                            else
                                temp_data[7] = last_temp_data[7] + 1;
                            ptr[7] = temp_data[7];
                        }
                        MEMCPY(last_temp_data,temp_data,8);             // Backup cur temp_data for next use
						if(pCBPageUpdate!=NULL)
							pCBPageUpdate(pDecRdCB->page_id,0x00);
					}
				}
			}
			// time filling end
		}
	}
	else if(packet == 27 )
	{
		if(page_start[mag] == 1)
		{
			if(mag != last_mag && transfer_mode==1)
				return ;
			data++;//designation = Ham_dec(*data++);
			for(i=0;i<6;i++)
			{
				link_page_id = x_link(data,mag);
				data += 6;
				if(i==0)
				{
					last_pCurWrCB[mag]->link_red =  link_page_id;
				}
				else if(i==1)
				{
					last_pCurWrCB[mag]->link_green= link_page_id;
				}
				else if(i==2)
				{
					last_pCurWrCB[mag]->link_yellow= link_page_id;
				}
				else if(i==3)
				{
					last_pCurWrCB[mag]->link_cyan = link_page_id;
				}
				else if(i==4)
				{
					last_pCurWrCB[mag]->link_next= link_page_id;
				}
				else if(i==5)
				{
					last_pCurWrCB[mag]->link_index = link_page_id;
				}
			}
		}
	}
	else if(packet <= 24 && packet >= 1)
	{
		if(mag>7)
			return;
		if(page_start[mag] == 1 && page_rec_data[mag]==1)// && packet >= last_line[mag])
		{
			if(mag != last_mag && transfer_mode==1)
				return ;
             //add by Colin for test
             // if(mag == 1 && page100_flag == TRUE)
             //     libc_printf("packet = %d\n",packet);
			//del extra packet
	//		if(transfer_mode==0 )
	//		{
			//	if(g_packet_exist[mag][packet]==1)
			//		return;
			//		for(i=0;i<40;i++)
			//		{
			//			if(Odd_dec(*(data+i))!=0x20)
			//				break;
			//		}
			//		if(i==40)
			//		{
			//			return;
			//		}
			//		for(i=1,j=0;i<23;i++)
			//		{
			//			if(g_packet_exist[mag][i]==1)//check how many packets are transferred
			//				j++;
			//		}
			//		if(last_packet[mag]<=24)
			//		{
			//			if(packet<last_packet[mag] && last_pCurWrCB[mag]->InterruptedSequence==0 && j!=0)
			//			{
			//				if(page_transfered_num>123)//some stream transfer packets without queue like R4_2006-02-16.ts
			//				return;
			//			}
			//		}
	//			}
//			if(transfer_mode==1)
//			{
				//if(g_packet_exist[mag][packet]==0 && last_packet[mag]<=24)
				//{
				//    if(packet<last_packet[mag] && last_pCurWrCB[mag]->UpdateIndicator==0 && last_pCurWrCB[mag]->InterruptedSequence==0
				//				&& !(last_packet[mag]==17 || last_packet[mag]==24&&packet==1) )
				//           return;
				//  }
//				if(g_packet_exist[mag][packet]==0 && last_packet[mag] == 26)
//				{
//					for(i=1,j=0;i<23;i++)
//					{
//						if(g_packet_exist[mag][i]==1)//check how many packets are transferred
//						j++;
//					}
//					if(j>1)
//						bCheck_p26 = TRUE;//cloud
//				}
				//if(g_packet_exist[mag][packet]==1 && packet !=17)//&& last_packet[mag]<=24)
				//   return;
//			}
			g_packet_exist[mag][packet]=1;//cloud
			if(packet == 24) last_pCurWrCB[mag]->pack24_exist = 1;
			ptr = last_pCurWrCB[mag]->buf_start + packet*40;
			for(i=0;i<40;i++)
			{
				/*	if((TRUE == g_vbi27_pconfig_par->parse_packet26_enable) &&
				(((g_ttx_p26_data[packet*40+i])>>7 == 1)||
				(((g_ttx_p26_data[packet*40+i])>>7 == 0)&&(get_packet26_nation_map(last_pCurWrCB[mag]->page_id, packet, i) == 0xf))))
				{
				*(ptr+i)= g_ttx_p26_data[packet*40+i];
				}*/
				if ((TRUE == g_vbi27_pconfig_par->parse_packet26_enable) &&
				((*(ptr+i)>>7 == 1)&&(get_packet26_nation_map(last_pCurWrCB[mag]->page_id, packet, i) != 0)||
				((*(ptr+i)>>7 == 0)&&(get_packet26_nation_map(last_pCurWrCB[mag]->page_id, packet, i) == 0xf))))
				{
					;
				}
				else                  
				{
					*(ptr+i)= Odd_dec(*(data+i));
				}
			}
			//if(mag==4) //&& last_page_number[mag]==2)
			//{
			//    libc_printf("packet=%d\n",packet);
			//    if(packet==1)
			//        libc_printf("0x%x,0x%x,0x%x,0x%x,0x%x\n",*(ptr),*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4));
			//}
		}
	}
	else if(packet == 28)
	{
		if(page_start[mag] == 1)
		{
			if(mag != last_mag && transfer_mode==1)
				return ;
			ham1 = hamming_8_4(*data);
			designation = ((ham1&0x40)>>6) + ((ham1&0x10)>>3) + (ham1&0x04) + ((ham1&0x01)<<3);
			if(designation != 0 && designation != 4)
				return;
			hamming_24_18(*(data+1),*(data+2),*(data+3),&ham1,&ham2,&ham3);
			last_pCurWrCB[mag]->G0_set = ((ham2&0x10)>>4) + ((ham2&0x08)>>2) +((ham2&0x04))+((ham2&0x02)<<2)
			+((ham3&0x80)>>3)+((ham3&0x40)>>1)+((ham3&0x20)<<1);
			last_pCurWrCB[mag]->Second_G0_set = ((ham3&0x10)>>4)+((ham3&0x08)>>2)+((ham3&0x04)<<1)+((ham3&0x02)<<2);
			hamming_24_18(*(data+4),*(data+5),*(data+6),&ham1,&ham2,&ham3);
			last_pCurWrCB[mag]->Second_G0_set += ((ham1&0x20)>>1) + ((ham1&0x08)<<2) +((ham1&0x04)<<4);
		}
	}
	else if(packet == 29)
	{
		if(page_start[mag] == 1)
		{
			if(mag != last_mag && transfer_mode==1)
				return ;
			ham1 = hamming_8_4(*data);
			designation = ((ham1&0x40)>>6) + ((ham1&0x10)>>3) + (ham1&0x04) + ((ham1&0x01)<<3);
			if(designation != 0 && designation != 4)
				return;
			hamming_24_18(*(data+1),*(data+2),*(data+3),&ham1,&ham2,&ham3);
			last_pCurWrCB[mag]->G0_set = ((ham2&0x10)>>4) + ((ham2&0x08)>>2) +((ham2&0x04))+((ham2&0x02)<<2)
			+((ham3&0x80)>>3)+((ham3&0x40)>>1)+((ham3&0x20)<<1);
			g0_set[mag] = last_pCurWrCB[mag]->G0_set;
			last_pCurWrCB[mag]->Second_G0_set = ((ham3&0x10)>>4)+((ham3&0x08)>>2)+((ham3&0x04)<<1)+((ham3&0x02)<<2);
			hamming_24_18(*(data+4),*(data+5),*(data+6),&ham1,&ham2,&ham3);
			last_pCurWrCB[mag]->Second_G0_set += ((ham1&0x20)>>1) + ((ham1&0x08)<<2) +((ham1&0x04)<<4);
			second_g0_set[mag] = last_pCurWrCB[mag]->Second_G0_set;
		}
	}
	else if((TRUE == g_vbi27_pconfig_par->parse_packet26_enable) && (packet == 26))
	{
		if(mag<=7 && page_start[mag] == 1 && page_rec_data[mag]==1)// && packet >= last_line[mag])
		{
			if(mag != last_mag && transfer_mode==1)
				return ;        		
			#ifdef PRINTF_PAGE_PACKET
			if(g_disable_p26&&last_pCurWrCB[mag]->page_id==g_debug_page_id)
				return;
			#endif
			for(i=1,j=0;i<=24;i++)//to fix bug in 29_07_04_TVC_TS.ts
			{
				if(g_packet_exist[mag][i]==1)
					j++;
			}
			if(j==1 && g_packet_exist[mag][j]==1)
				g_packet_exist[mag][j]=0;

			for(i = 0; i < 13; i++)
			{
				hamming_24_18(*(data+1+i*3),*(data+1+i*3+1),*(data+1+i*3+2),&ham1,&ham2,&ham3);
				p26_address = ((ham1&0x20)>>5) + ((ham1&0x08)>>2) +(ham1&0x04) + ((ham1&0x02)<<2) + ((ham2&0x80)>>3) + ((ham2&0x40)>>1);
				p26_mode = ((ham2&0x20)>>5) + ((ham2&0x10)>>3) + ((ham2&0x08)>>1) + ((ham2&0x04)<<1) + ((ham2&0x02)<<3);
				p26_data = ((ham3&0x80)>>7) + ((ham3&0x40)>>5) + ((ham3&0x20)>>3) + ((ham3&0x10)>>1) + ((ham3&0x08)<<1) + ((ham3&0x04)<<3) + ((ham3&0x02)<<5);
				//if(pCurWrCB[mag]->page_id==100 )//&& pCurWrCB[mag]->sub_page_id==7)
				//    libc_printf("p26_address=%d,p26_mode=0x%x,p26_data=0x%x\n",p26_address,p26_mode,p26_data);
				p26_data = p26_data&0x7F;//cloud
				if(i==0 && last_pCurWrCB[mag]->page_id==last_p26_page_id && bPacket26==TRUE
				&&((TRUE == g_vbi27_pconfig_par->ttx_sub_page) 
				&&  last_pCurWrCB[mag]->sub_page_id==last_p26_sub_page_id)) //cloud
				{
					col=last_col;
					row=last_row;
					bPacket26=FALSE;
				}
				if (p26_address < 40)
				{
					col = p26_address;
					if(i==12)
					{
						last_row = row;
						last_col = col;//cloud
						last_p26_page_id = last_pCurWrCB[mag]->page_id;//cloud
						if(TRUE == g_vbi27_pconfig_par->ttx_sub_page)
						last_p26_sub_page_id = last_pCurWrCB[mag]->sub_page_id;
						bPacket26 = TRUE;
					}
					// col functions
					switch (p26_mode)
					{
						case 2://G3 set
							if(p26_data==0x5d || p26_data==0x5b)//reuse font to save code size,cloud
							{
								SET_P26_NATION_MAP(last_pCurWrCB[mag]->page_id, row, col, 0xf);
								if(p26_data==0x5d)
									p26_data = 0x2d;
								else
									p26_data = 0x2e;
								p26_data=p26_data&0x7F;//cloud
								//g_ttx_p26_data[row*40+col] = p26_data;
								*(last_pCurWrCB[mag]->buf_start + row*40+col) = p26_data;
								g_packet_exist[mag][row] = 26;
								#ifdef PRINTF_PAGE_PACKET
								if(g_debug_p26&&last_pCurWrCB[mag]->page_id==g_debug_page_id)
									libc_printf("G3(%d,%d:%d),",row,col,p26_data);
								#endif
							}
							break;
						case 15: // char from G2 set
							if (col < 40 && row < 25)
							{
								if(p26_data < 127 && (row!=0))
								{
									//if(row!=0)//cloud
									SET_P26_NATION_MAP(last_pCurWrCB[mag]->page_id, row, col, 0xf);
									p26_data=p26_data&0x7F;//cloud
									//g_ttx_p26_data[row*40+col] = p26_data;
									*(last_pCurWrCB[mag]->buf_start + row*40+col) = p26_data;
									g_packet_exist[mag][row] = 26;
								}
								#ifdef PRINTF_PAGE_PACKET
								if(g_debug_p26&&last_pCurWrCB[mag]->page_id==g_debug_page_id)
									libc_printf("G2(%d,%d:%d),",row,col,p26_data);
								#endif
							}
							break;
						case 16 ... 31: // char from G0 set with diacritical mark
							if (col < 40 && row < 25 && row!=0)
							{
								p26_nation = p26_mode - 16;//cloud
								SET_P26_NATION_MAP(last_pCurWrCB[mag]->page_id, row, col, p26_nation);//cloud
								p26_data=p26_data|0x80;//cloud
								//g_ttx_p26_data[row*40+col] = p26_data;//cloud
								*(last_pCurWrCB[mag]->buf_start + row*40+col) = p26_data;
								g_packet_exist[mag][row] = 26;
								#ifdef PRINTF_PAGE_PACKET
								if(g_debug_p26&&last_pCurWrCB[mag]->page_id==g_debug_page_id)
									libc_printf("DM(%d,%d:%d),",row,col,p26_data);
								#endif
							}
							break;
						default:
							break;
					}
				}
				else
				{
					// row functions
					if ((p26_address -= 40) == 0)
						p26_address = 24;
					switch (p26_mode)
					{
						case 1: // full row color
							row = p26_address;
							break;
						case 4: // set active position                  
							row = p26_address;
							if(p26_data<40)
								col = p26_data;//cloud
							if(i==12)
							{
								last_row = row;
								last_col = col;//cloud
								last_p26_page_id = last_pCurWrCB[mag]->page_id;//cloud
								if(TRUE == g_vbi27_pconfig_par->ttx_sub_page)
									last_p26_sub_page_id = last_pCurWrCB[mag]->sub_page_id;
								bPacket26 = TRUE;
							}
							break;
						case 7: // address row 0 (+ full row color)
							if(p26_address == 23)
								row = 0;
							break;
						case 31:
							if (p26_address == 23)//Termination Marker
							{                      
								last_packet[mag]=26;
								return;
							}
							break;
						default: 
							break;
					}
				}
			}
		}
	}
	else if(packet == 30)//cloud,only get initial page now
	{
		data++;
		abs_mag = x_packet_30(data,&head);
		if(head.page != 0xff) 
		{
			page_id = Hex2Dec( (abs_mag<<8) + head.page); //100 ~899,0~99->800~899
			//libc_printf("page_id=%d\n",page_id);
			//fix BUG17068, for init page point to the page which is not exists.
			if( page_id == 0xffff ||(page_id!=100 &&pbf_rd_req(page_id, &check_cb)!=RET_SUCCESS) )
			{
				//libc_printf(".");
				return;    
			}
			g_inital_page = page_id;
		}
	}
	else
	{
		//VBI_PRINTF("\np%d  \n",packet);
	}
	if(packet<=29)
		last_packet[mag]=packet;
	return ;
	/*	else if(packet == 30)
	{
		//VBI_PRINTF("packet == %d  \n",packet);
		if(page_start == 1)
		{
			designation = Ham_dec(*data++);
			for(i=0;i<6;i++)
			{
				for(j=0;j<6;j++)
				{
					vector[j] = *data++;
				}
				x_link(i,vector,pCurWrCB);
			}
		}
	}
	else if(packet == 31)
	{
	//VBI_PRINTF("packet == %d  \n",packet);
		if(page_start == 1)
		{
			designation = Ham_dec(*data++);
			for(i=0;i<6;i++)
			{
				for(j=0;j<6;j++)
				{
					vector[j] = *data++;
				}
				x_link(i,vector,pCurWrCB);
			}
		}
	}
	*/
}
INT32 ttx_m3327_request_page(struct vbi_device *dev, UINT16 page_id , struct PBF_CB ** cb )
{

	INT32 ret;
	ret = pbf_rd_req(page_id, cb) ;

	if(ret == RET_SUCCESS)
	{

		pDecRdCB = *cb;
		rd_page = pDecRdCB->page_id;
		return RET_SUCCESS;
	}
	else
		return RET_FAILURE;

}
INT32 ttx_m3327_request_page_up(struct vbi_device *dev,UINT16 page_id , struct PBF_CB ** cb )
{
INT32 ret;
	ret =pbf_rd_req_up(page_id, cb);
	if(ret == RET_SUCCESS)
	{
		pDecRdCB = *cb;
		rd_page = pDecRdCB->page_id;
		return RET_SUCCESS;
	}
	else
		return RET_FAILURE;
	//return pbf_rd_req_up(page_id, cb);

}
INT32 ttx_m3327_request_page_down(struct vbi_device *dev, UINT16 page_id , struct PBF_CB ** cb )
{
INT32 ret;
ret =pbf_rd_req_down(page_id, cb);
	if(ret == RET_SUCCESS)
	{
		pDecRdCB = *cb;
		rd_page = pDecRdCB->page_id;
		return RET_SUCCESS;
	}
	else
		return RET_FAILURE;
	//return pbf_rd_req_down(page_id, cb);
}
void ttx_m3327_default_g0_set(struct vbi_device *dev, UINT8 default_g0_set)
{
	g_default_g0_set = default_g0_set;
}

/*
	NAME 			:	 vbi_m3327_init_ttx_decoder(void)
	DESCRIPTION		: 	 init the teletext decoder
	PARAMETERS		:	NONE
	RETURN			:	void
*/
void vbi_m3327_init_ttx_decoder(void)
{
	int i = 0;

	pCBPageUpdate = NULL;
	rd_page = 0xffff;
   
	for(i=0;i<8;i++)
	{
		page_start[i] = 0;
		g0_set[i] = g_default_g0_set<<3;
		second_g0_set[i]= 0;//g0_set[i];
		//last_line[i] = 0;
	}
	transfer_mode = 1;
    last_transfer_mode =1;
	last_mag = 0xf;//1;
	bShowPage=FALSE;//cloud
	g_inital_page = 0xFF;//cloud
	last_p26_page_id = 0;
    last_p26_sub_page_id = 0;
    page_transfered_num = 0; //cloud
    first_ttx_page = 0xff;
   	ttx_subt_alarm_id = OSAL_INVALID_ID;
//    page_erase = FALSE;
//  last_tmp_tick = osal_get_tick();
}

void vbi_enable_ttx_by_osd(struct vbi_device*pdev)
{
	struct vbi_m3327_private *priv = (struct vbi_m3327_private *)(pdev->priv);

	pdev->request_page = ttx_m3327_request_page;
	pdev->request_page_up = ttx_m3327_request_page_up;
	pdev->request_page_down = ttx_m3327_request_page_down;
	pdev->default_g0_set = ttx_m3327_default_g0_set;
	
	priv->ttx_by_osd = TRUE;
	priv->init_ttx_decoder = vbi_m3327_init_ttx_decoder;
}

void vbi_disable_ttx_by_osd()//add for 3101
{
    struct vbi_device *vbi_dev = NULL;
    vbi_dev = (struct vbi_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_VBI);

    if(vbi_dev==NULL)
        ASSERT(0);
    
    struct vbi_m3327_private *priv = (struct vbi_m3327_private *)(vbi_dev->priv);

    vbi_dev->request_page = NULL;
	vbi_dev->request_page_up = NULL;
	vbi_dev->request_page_down = NULL;
	vbi_dev->default_g0_set = NULL;
    
	priv->ttx_by_osd = FALSE;
	priv->init_ttx_decoder = NULL;   
}
